package com.linshengjian.snowball.annotation.translate;

import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.Serializable;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 基础类型的转义
 */
@Component
public class BasicConvertHandler implements IConvertHandler {

    boolean isEmpty(String str) {
        return str == null || "".equals(str);
    }

    private String numberTo(Number number, String format) {
        if (isEmpty(format)) {
            return number.toString();
        }

        DecimalFormat df = new DecimalFormat(format);

        return df.format(number);
    }

    private Number numberTo(Number number, Class targetType) {
        if (targetType.equals(Double.class)) {
            return number.doubleValue();
        } else if (targetType.equals(Float.class)) {
            return number.floatValue();
        } else if (targetType.equals(Integer.class)) {
            return number.intValue();
        } else if (targetType.equals(Long.class)) {
            return number.longValue();
        } else if (targetType.equals(Short.class)) {
            return number.shortValue();
        }
        return 0;
    }

    private Number stringTo(String str, Class targetType, String format) throws ParseException {

        if (isEmpty(format)) {
            if (targetType.equals(Double.class)) {
                return Double.valueOf(str);
            } else if (targetType.equals(Float.class)) {
                return Float.valueOf(str);
            } else if (targetType.equals(Integer.class)) {
                return Integer.valueOf(str);
            } else if (targetType.equals(Long.class)) {
                return Long.valueOf(str);
            } else if (targetType.equals(Short.class)) {
                return Short.valueOf(str);
            }
        } else {
            DecimalFormat df = new DecimalFormat(format);
            if (targetType.equals(Double.class)) {
                return df.parse(str).doubleValue();
            } else if (targetType.equals(Float.class)) {
                return df.parse(str).floatValue();
            } else if (targetType.equals(Integer.class)) {
                return df.parse(str).intValue();
            } else if (targetType.equals(Long.class)) {
                return df.parse(str).longValue();
            } else if (targetType.equals(Short.class)) {
                return df.parse(str).shortValue();
            }
        }

        return null;
    }

    protected String getTargetTypeStr(Class targetType) {
        switch (targetType.getName()) {
            case "byte": return Byte.class.getName();
            case "short": return Short.class.getName();
            case "int": return Integer.class.getName();
            case "long": return Long.class.getName();
            case "float": return Float.class.getName();
            case "double": return Double.class.getName();
            case "boolean": return Boolean.class.getName();
            case "char": return Character.class.getName();
            default: return targetType.getName();
        }
    }

    @Override
    public Object handler(Object sourceValue, String format, Class targetType) throws Exception {

        if (sourceValue == null)
            return null;

        if (sourceValue instanceof Number) {
            // 数字转换成字符串
            if (String.class.getName().equals(getTargetTypeStr(targetType))) {
                return numberTo((Number) sourceValue, format);
            }
            // 数值转换成其他数值类型
            if (Number.class.isAssignableFrom(targetType)) {
                return numberTo((Number) sourceValue, targetType);
            }
            // 数值转换成时间
            if (targetType.equals(Date.class)) {
                return new Date(((Number)sourceValue).longValue());
            }
        }

        if (sourceValue instanceof String) {
            // 字符串转时间
            if (Number.class.isAssignableFrom(targetType)) {
                return stringTo((String) sourceValue, targetType, format);
            }
            // 字符串的时间，转时间类型
            if (targetType.equals(Date.class)) {
                if (isEmpty(format)) {
                    format = "yyyy-MM-dd HH:mm:dd";
                }

                return new SimpleDateFormat(format).parse((String) sourceValue);
            }

            if (String.class.getName().equals(getTargetTypeStr(targetType))) {
                if (StringUtils.isEmpty(format))
                    return sourceValue;
                else
                    return String.format(format, sourceValue);
            }
        }

        if (sourceValue instanceof Date) {
            // 时间类型装数值
            if (Number.class.isAssignableFrom(targetType)) {
                return ((Date)sourceValue).getTime();
            }
            // 时间类型转字符
            if (targetType.equals(String.class)) {
                if (isEmpty(format)) {
                    format = "yyyy-MM-dd HH:mm:dd";
                }

                return new SimpleDateFormat(format).format(sourceValue);
            }

            if (targetType.equals(Date.class)) {
                return sourceValue;
            }
        }

        if (sourceValue instanceof Boolean) {
            // 布尔值转字符
            if (targetType.equals(String.class)) {
                return sourceValue.toString();
            }
            // 布尔值转数值
            if (Number.class.isAssignableFrom(targetType)) {
                return (Boolean)sourceValue ? 1 : 0;
            }
        }

        // 类型是一样的，直接转
        if (sourceValue.getClass().getName().equals(getTargetTypeStr(targetType)))
            return sourceValue;

        // 都是 Serializable类型的
        if (Serializable.class.equals(targetType)) {
            if (sourceValue instanceof Serializable)
                return sourceValue;
        }

        return null;
    }
}
